C++ 清理内存

资源获得即初始化惯用法 RAII

RAII (Resource Acquisition Is Initialization) 用于一个实例离开作用域时自动释放已获取资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
using namespace std;

//假设这是一个会占用较大堆空间的类型
class Message
{
public:
Message() : val{"这是一个非常长的字符串"} {
}
~Message() { }
void SendMessage() {
cout << val << endl;
}
string val;
};

//这个类型负责管理Message对象的释放工作
class MessageRAII {
public:
MessageRAII() : msgObj{ new Message() } { };
Message* get() {
return msgObj;
}
~MessageRAII() {
delete msgObj;
}
Message* msgObj;
};

//入口函数
int main() {
{
// 在栈上声明一个代理类型,负责管理目标对象
// 代理类型自身会在离开作用域时销毁
MessageRAII msgRAIIobj;
msgRAIIobj.get()->SendMessage();
}
auto c = getchar();
}

智能指针

  • 代理对象,智能管理内存
  • 通过 ->* 解引用访问代理对象
  • 通过 . 访问自身的管理方法

共享指针 shared_ptr

more info

  • 自动释放关联的堆空间

  • 同一对象可被多个共享指针持有

    • 内部记录该类型的引用个数
    • 引用记数为 0时,释放内存
  • 定义方法

    • ```c++
      shared_ptr myClass0 = make_shared();

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20

      - `shared_ptr` 定义指针

      - `make_shared` 初始化,如果 MyClass 构造函数有参数,通过 `make_shared` 传递

      - 在 `memory` 头文件定义

      - 尖括号中放置共享指针的类型

      - 通过共享指针的 `use_count` 方法检查堆空间一共存在多少个共享指针引用

      - myClass0.use_count();

      - **如果一个共享指针被重新赋值(让共享指针指向一个全新的对象),那么该共享指针被重新赋值前关联的堆空间的引用计数会减一**

      - ```c++
      {
      auto myClass1 = make_shared<MyClass>();
      myClass1 = make_shared<MyClass>();
      }
      • 上面的代码, MyClass 的析构函数会执行两次,第一次是智能指针 myClass1 被重新赋值时,第二次是智能指针 myClass1 超出作用域之后
  • 成员函数

    • swap
    • reset
    • get
    • use_count
    • unique

独占指针 unique_ptr

more info

  • 自动释放关联的堆空间

  • 同一对象只能被一个独占指针持有

  • 定义方法

    • ```c++
      unique_ptr myClass = make_unique();
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10

      - **如果一个独占指针被重新赋值,那么该独占指针被重新赋值前,其关联的堆空间会被立即释放**,使用 reset 重新绑定

      - 独占指针的 `reset` 方法立即释放堆内存

      - ```c++
      auto myClass = make_unique<MyClass>();
      myClass.reset();
      // 或者像 reset 传入新的类型指针
      // myClass.reset(new Cls());
  • 成员函数

    • get 获取代理对象指针
    • get_deleter
    • release 释放对象,返回原始对指针
    • reset
    • swap

弱指针 weak_ptr

more info

用来解决共享指针的循环引用问题

作者

大下坡

发布于

2023-11-11

更新于

2023-11-11

许可协议